import pyaudio,audioop,Queue,threading,binascii,time
from defs import *

class audio_interface(threading.Thread):
	def __init__(self,identifier,outfunc):
		threading.Thread.__init__(self)
		self.is_closing=False
		self.active=False
		self.identifier=identifier
		self.readbuf=""
		self.writebuf=""
		self.codec=codec()
		self.outfunc=outfunc
		try:
			self.p = pyaudio.PyAudio()
			self.stream_r = self.p.open(format=pyaudio.paInt16,channels = 1,rate = 8000,input = True, output = False,frames_per_buffer = 1024)
			self.stream_w = self.p.open(format=pyaudio.paInt16,channels = 1,rate = 8000,input = False, output = True,frames_per_buffer = 1024)
			#print self.p.get_default_host_api_info()
			print self.p.get_host_api_info_by_type(pyaudio.paMME)
		except IOError, e:
			logger.error("Audio interface can not be initialized :  %s" ,e)
			return None
		logger.info("Audio interface initialized")
		self.start()
			
	def close(self):
		self.is_closing=True
		try:
			self.stream_w.close()
			self.stream_r.close()
		except IOError, e:
			logger.error("Audio interface can not be closed :  %s retrying" ,e)
			self.close()
		threading.Thread.join(self)
		return True

	def run(self):
		bite=(udp_packet_size-max_header)*2
		t1=0
		while 1:
			chunk=self.stream_r.get_read_available()
			if (not self.is_closing) and chunk and self.active:
				try:
					self.readbuf+=self.stream_r.read(chunk)
					while len(self.readbuf) > bite:
						payloadbuf=self.readbuf[:bite]
						self.readbuf=self.readbuf[bite:]
						payload=self.codec.compress(payloadbuf)
						diff=(time.time()-t1)
						if diff>0:
							print "audio read speed--------------------------(" + str(int(len(payload)/diff/1000)) + ")-----------------"
						self.outfunc(self.identifier,"audio",payload)
						t1=time.time()

				except IOError,e:
					logger.error("Audio interface cant read stream: %s",e)
					continue
			elif self.is_closing:
				return

	def write(self,payload):
		self.writebuf+=payload
		if len(self.writebuf) < 2048:	
			return
		while 1:
			if len(self.writebuf)%2!=0:
				swap=-1
			else:
				swap=-2
			audio=self.codec.decompress(self.writebuf[:swap])
			self.writebuf=self.writebuf[swap:]
			try:
				self.stream_w.write(audio)
			except IOError, e:
				logger.error("Audio interface cant write %d byte to stream: %s",asciisize(audio),e)
				return False
			if len(self.writebuf) < 10:
				return True


class codec():
	def __init__(self):
		logger.info("Codecs initialized")
	def compress(self,audio):
		try:
			return audioop.lin2ulaw(audio, 2)
		except audioop.error,e:
			logger.error("Codec cant encode %d byte aduio : %s",asciisize(audio),e)
			return ""
	
	def decompress(self,payload):
		try:
			return audioop.ulaw2lin(payload, 2)
		except audioop.error, e:
			logger.error("Codec cant decode %d byte aduio : %s",asciisize(payload),e)
#			hex=binascii.hexlify(payload)
#			print str(len(hex)/2)+ " : " + str(hex)
#			print binascii.hexlify(payload[-1:])
			return ""
